package de.urw.app;


public class Vector3d {

	public double x,y,z;
	public Vector3d(){
		this.x = 0;
		this.y = 0;
		this.z = 0;
	}
	public Vector3d(double x,double y,double z){
		this.x = x;
		this.y = y;
		this.z = z;
	}
	
	public Vector3d add (Vector3d v){
		Vector3d r =  this.duplicate();
		r.x += v.x;
		r.y += v.y;
		r.z += v.z;
		return r;
	}
	
	public Vector3d sub (Vector3d v){
		Vector3d r = (Vector3d) this.duplicate();
		r.x -= v.x;
		r.y -= v.y;
		r.z -= v.z;
		return r;
	}
	
	public Vector3d cross (Vector3d v){
		Vector3d r = new Vector3d();
		r.x = this.y*v.z - this.z * v.y;
		r.y = this.z*v.x - this.x * v.z;
		r.z = this.x*v.y - this.y * v.x;
		return r;
	}
	
	public double dot (Vector3d v){
		return this.x*v.x + this.y*v.y + this.z*v.z;
	}
	
	public double magnitude (){
		return Math.sqrt(this.dot(this));
	}
	
	public double carthesian(int i){
		switch (i){
		case 1:
			return this.x;
		case 2:
			return this.y;
		case 3:
			return this.z;
		}
		return 0;
	}
	
	public Vector3d times (double factor){
		Vector3d r = (Vector3d) this.duplicate();
		r.x *= factor;
		r.y *= factor;
		r.z *= factor;
		return r;		
	}
	
	public double distanceTo (Vector3d v){
		return this.sub(v).magnitude();
	}
	
	public Vector3d normalize (){
		Vector3d r = this.duplicate();
		double n = this.magnitude();
		r.x /= n;
		r.y /= n;
		r.z /= n;	
		return r;
	}
	
	public Vector3d rotateVector(Vector3d v, double angle){
		Vector3d n = v.normalize();
		Vector3d r = new Vector3d();
		double ca = Math.cos(angle);
		double sa = Math.sin(angle);
		r.x = this.x*(n.y*n.y*(1-ca)+ca) 		+ this.y*(n.x*n.y*(1-ca)-n.z*sa) 	+ this.z*(n.x*n.z*(1-ca)+n.y*sa) ;
		r.y = this.x*(n.x*n.y*(1-ca)+n.z*sa) 	+ this.y*(n.y*n.y*(1-ca)+ca) 		+ this.z*(n.y*n.z*(1-ca)+n.x*sa) ;
		r.z = this.x*(n.y*n.z*(1-ca)-n.y*sa)	+ this.y*(n.y*n.z*(1-ca)+n.x*sa) 	+ this.z*(n.y*n.y*(1-ca)+ ca) ;
		return r;
	}
	
	public Vector3d rotateX(double angle){
		return this.rotateVector(new Vector3d(1,0,0), angle);
	}
	
	public Vector3d rotateY(double angle){
		return this.rotateVector(new Vector3d(0, 1, 0), angle);
	}
	
	public Vector3d rotateZ(double angle){
		return this.rotateVector(new Vector3d(0,0,1), angle);
	}
	
	private Vector3d duplicate() {
		Vector3d r = new Vector3d();
		r.x = this.x;
		r.y = this.y;
		r.z = this.z;
		return r;
	}
	
	public String toString() {
        return  "("
        		+ "x:"+ x
        		+ "y:"+ y
        		+ "z:"+ z
        		+ ")"; 
    }
	
}
